/* $Id$ */
package org.crazydays.gameplan.view;


import java.lang.reflect.Method;
import java.util.Map;

import javax.swing.JDesktopPane;
import javax.swing.JInternalFrame;
import javax.swing.event.InternalFrameEvent;

import org.junit.*;
import static org.junit.Assert.*;

import static org.easymock.EasyMock.*;
import static org.easymock.classextension.EasyMock.*;

import org.crazydays.gameplan.Actions;
import org.crazydays.gameplan.Controller;
import org.crazydays.gameplan.db.Database;
import org.crazydays.gameplan.map.GameMap;
import org.crazydays.gameplan.map.GridType;
import org.crazydays.gameplan.map.IGameMap;
import org.crazydays.gameplan.map.event.ToggleGrid;
import org.crazydays.gameplan.map.swing.JMapFrame;
import org.crazydays.gameplan.model.Model;
import org.crazydays.gameplan.swing.JLogoDesktopPane;
import org.crazydays.gameplan.view.View;

/**
 * ViewUnitTest
 */
public class ViewUnitTest
{
    /**
     * Test constructor.
     */
    @Test
    public void testConstructor()
    {
        // mocks
        Controller controller = createMock(Controller.class);
        Model model = createMock(Model.class);

        // replay
        replay(controller, model);

        // test
        View view = new View(controller, model);

        // verify
        verify(controller, model);

        assertEquals("view.controller", controller, view.controller);
        assertEquals("view.model", model, view.model);
    }

    /**
     * Test initialize.
     * 
     * @throws NoSuchMethodException
     * @throws SecurityException
     */
    @Test
    public void testInitialize()
        throws SecurityException, NoSuchMethodException
    {
        // mocks
        View view =
            createMock(View.class, new Method[] {
                View.class.getDeclaredMethod("initializeListeners"),
                View.class.getDeclaredMethod("buildMenus"),
                View.class.getDeclaredMethod("initializeSplitPane"), });

        // expect
        view.initializeListeners();
        view.buildMenus();
        view.initializeSplitPane();

        // replay
        replay(view);

        // test
        view.initialize();

        // verify
        verify(view);
    }

    /**
     * Test open(IGameMap).
     */
    @Test
    public void testOpen()
    {
        // mocks
        Controller controller = createMock(Controller.class);
        Model model = createMock(Model.class);
        JLogoDesktopPane desktopPane = createMock(JLogoDesktopPane.class);

        // objects
        IGameMap gameMap = new GameMap("name", 600, 800, GridType.SQUARE, 20);
        Actions actions = new Actions(controller);

        // expect
        expect(controller.getActions()).andReturn(actions);
        expect(desktopPane.add(isA(JMapFrame.class))).andReturn(null);
        desktopPane.moveToFront(isA(JMapFrame.class));

        // replay
        replay(controller, model, desktopPane);

        // setup
        View view = new View(controller, model);
        view.desktopPane = desktopPane;

        // test
        view.open(gameMap);

        // verify
        verify(controller, model, desktopPane);
    }

    /**
     * Test opened(Database).
     */
    @Test
    public void testOpened()
    {
        // mocks
        Controller controller = createMock(Controller.class);
        Model model = createMock(Model.class);
        Database database = createMock(Database.class);

        // replay
        replay(controller, model, database);

        // setup
        View view = new View(controller, model);

        // test
        view.opened(database);

        // verify
        verify(controller, model, database);
    }

    /**
     * Test closed(Database).
     */
    @Test
    public void testClosed()
    {
        // mocks
        Controller controller = createMock(Controller.class);
        Model model = createMock(Model.class);
        Database database = createMock(Database.class);
        JDesktopPane desktopPane = createMock(JDesktopPane.class);
        JInternalFrame frame = createMock(JInternalFrame.class);
        @SuppressWarnings("unchecked")
        Map<String, JMapFrame> openGameMaps = createMock(Map.class);

        // expect
        expect(desktopPane.getAllFrames()).andReturn(
            new JInternalFrame[] { frame });
        frame.dispose();
        openGameMaps.clear();

        // replay
        replay(controller, model, database, desktopPane, frame, openGameMaps);

        // setup
        View view = new View(controller, model);
        view.desktopPane = desktopPane;
        view.openGameMaps = openGameMaps;

        // test
        view.closed(database);

        // verify
        verify(controller, model, database, desktopPane, frame, openGameMaps);
    }

    /**
     * Test internalFrameOpened(InternalFrameEvent).
     */
    @Test
    public void testInternalFrameOpened()
    {
        // mocks
        Controller controller = createMock(Controller.class);
        Model model = createMock(Model.class);
        InternalFrameEvent event = createMock(InternalFrameEvent.class);

        // setup
        View view = new View(controller, model);

        // replay
        replay(controller, model, event);

        // test
        view.internalFrameOpened(event);

        // verify
        verify(controller, model, event);
    }

    /**
     * Test internalFrameActivated(InternalFrameEvent).
     */
    @Test
    public void testInternalFrameActivated_grid_on()
    {
        // mocks
        Controller controller = createMock(Controller.class);
        Model model = createMock(Model.class);
        InternalFrameEvent event = createMock(InternalFrameEvent.class);
        JMapFrame frame = createMock(JMapFrame.class);
        Actions actions = createMock(Actions.class);
        ToggleGrid gridToggle = createMock(ToggleGrid.class);

        // expect
        expect(event.getInternalFrame()).andReturn(frame);
        expect(controller.getActions()).andReturn(actions);
        actions.enableMapOptions();
        expect(frame.isGridVisible()).andReturn(true);
        expect(controller.getActions()).andReturn(actions);
        expect(actions.getToggleGrid()).andReturn(gridToggle);
        gridToggle.setIconCross();

        // replay
        replay(controller, model, event, frame, actions, gridToggle);

        // setup
        View view = new View(controller, model);

        // test
        view.internalFrameActivated(event);

        // verify
        verify(controller, model, event, frame, actions, gridToggle);
    }

    /**
     * Test internalFrameActivated(InternalFrameEvent).
     */
    @Test
    public void testInternalFrameActivated_grid_off()
    {
        // mocks
        Controller controller = createMock(Controller.class);
        Model model = createMock(Model.class);
        InternalFrameEvent event = createMock(InternalFrameEvent.class);
        JMapFrame frame = createMock(JMapFrame.class);
        Actions actions = createMock(Actions.class);
        ToggleGrid gridToggle = createMock(ToggleGrid.class);

        // expect
        expect(event.getInternalFrame()).andReturn(frame);
        expect(controller.getActions()).andReturn(actions);
        actions.enableMapOptions();
        expect(frame.isGridVisible()).andReturn(false);
        expect(controller.getActions()).andReturn(actions);
        expect(actions.getToggleGrid()).andReturn(gridToggle);
        gridToggle.setIconTick();

        // replay
        replay(controller, model, event, frame, actions, gridToggle);

        // setup
        View view = new View(controller, model);

        // test
        view.internalFrameActivated(event);

        // verify
        verify(controller, model, event, frame, actions, gridToggle);
    }

    /**
     * Test internalFrameIconified(InternalFrameEvent).
     */
    @Test
    public void testInternalFrameIconified()
    {
        // mocks
        Controller controller = createMock(Controller.class);
        Model model = createMock(Model.class);
        InternalFrameEvent event = createMock(InternalFrameEvent.class);

        // setup
        View view = new View(controller, model);

        // replay
        replay(controller, model, event);

        // test
        view.internalFrameIconified(event);

        // verify
        verify(controller, model, event);
    }

    /**
     * Test internalFrameDeiconified(InternalFrameEvent).
     */
    @Test
    public void testInternalFrameDeiconified()
    {
        // mocks
        Controller controller = createMock(Controller.class);
        Model model = createMock(Model.class);
        InternalFrameEvent event = createMock(InternalFrameEvent.class);

        // setup
        View view = new View(controller, model);

        // replay
        replay(controller, model, event);

        // test
        view.internalFrameDeiconified(event);

        // verify
        verify(controller, model, event);
    }

    /**
     * Test internalFrameDeactivated(InternalFrameEvent).
     */
    @Test
    public void testInternalFrameDeactivated()
    {
        // mocks
        Controller controller = createMock(Controller.class);
        Model model = createMock(Model.class);
        InternalFrameEvent event = createMock(InternalFrameEvent.class);
        JMapFrame frame = createMock(JMapFrame.class);
        Actions actions = createMock(Actions.class);

        // expect
        expect(event.getInternalFrame()).andReturn(frame);
        expect(controller.getActions()).andReturn(actions);
        actions.disableMapOptions();

        // replay
        replay(controller, model, event, frame, actions);

        // setup
        View view = new View(controller, model);

        // test
        view.internalFrameDeactivated(event);

        // verify
        verify(controller, model, event, frame, actions);
    }

    /**
     * Test internalFrameClosing(InternalFrameEvent).
     */
    @Test
    public void testInternalFrameClosing()
    {
        // mocks
        Controller controller = createMock(Controller.class);
        Model model = createMock(Model.class);
        InternalFrameEvent event = createMock(InternalFrameEvent.class);

        // setup
        View view = new View(controller, model);

        // replay
        replay(controller, model, event);

        // test
        view.internalFrameClosing(event);

        // verify
        verify(controller, model, event);
    }

    /**
     * Test internalFrameClosed(InternalFrameEvent).
     */
    @Test
    public void testInternalFrameClosed()
    {
        // objects
        String name = "name";

        // mocks
        Controller controller = createMock(Controller.class);
        Model model = createMock(Model.class);
        InternalFrameEvent event = createMock(InternalFrameEvent.class);
        JMapFrame frame = createMock(JMapFrame.class);
        IGameMap gameMap = createMock(IGameMap.class);

        // setup
        View view = new View(controller, model);
        view.openGameMaps.put(name, frame);

        // expect
        expect(event.getInternalFrame()).andReturn(frame);
        expect(frame.getGameMap()).andReturn(gameMap).anyTimes();
        expect(gameMap.getName()).andReturn(name).anyTimes();
        frame.removeInternalFrameListener(view);

        // replay
        replay(controller, model, event, frame, gameMap);

        // test
        view.internalFrameClosed(event);

        // verify
        verify(controller, model, event, frame, gameMap);
        assertTrue("openGameMap", view.openGameMaps.isEmpty());
    }

    /**
     * Test toggleGrid().
     */
    @Test
    public void testToggleGrid_not_map()
    {
        // mocks
        Controller controller = createMock(Controller.class);
        Model model = createMock(Model.class);
        JDesktopPane desktopPane = createMock(JDesktopPane.class);
        JInternalFrame frame = createMock(JInternalFrame.class);

        // setup
        View view = new View(controller, model);
        view.desktopPane = desktopPane;

        // expect
        expect(desktopPane.getSelectedFrame()).andReturn(frame);

        // replay
        replay(controller, model, desktopPane, frame);

        // test
        boolean result = view.toggleGrid();

        // verify
        verify(controller, model, desktopPane, frame);

        assertEquals("result", false, result);
    }

    /**
     * Test toggleGrid().
     */
    @Test
    public void testToggleGrid_make_visible()
    {
        // mocks
        Controller controller = createMock(Controller.class);
        Model model = createMock(Model.class);
        JDesktopPane desktopPane = createMock(JDesktopPane.class);
        JMapFrame mapFrame = createMock(JMapFrame.class);

        // setup
        View view = new View(controller, model);
        view.desktopPane = desktopPane;

        // expect
        expect(desktopPane.getSelectedFrame()).andReturn(mapFrame);
        expect(mapFrame.isGridVisible()).andReturn(false);
        mapFrame.setGridVisible(true);
        expect(mapFrame.isGridVisible()).andReturn(true);

        // replay
        replay(controller, model, desktopPane, mapFrame);

        // test
        boolean result = view.toggleGrid();

        // verify
        verify(controller, model, desktopPane, mapFrame);

        assertEquals("result", true, result);
    }

    /**
     * Test toggleGrid().
     */
    @Test
    public void testToggleGrid_make_invisible()
    {
        // mocks
        Controller controller = createMock(Controller.class);
        Model model = createMock(Model.class);
        JDesktopPane desktopPane = createMock(JDesktopPane.class);
        JMapFrame mapFrame = createMock(JMapFrame.class);

        // setup
        View view = new View(controller, model);
        view.desktopPane = desktopPane;

        // expect
        expect(desktopPane.getSelectedFrame()).andReturn(mapFrame);
        expect(mapFrame.isGridVisible()).andReturn(true);
        mapFrame.setGridVisible(false);
        expect(mapFrame.isGridVisible()).andReturn(false);

        // replay
        replay(controller, model, desktopPane, mapFrame);

        // test
        boolean result = view.toggleGrid();

        // verify
        verify(controller, model, desktopPane, mapFrame);

        assertEquals("result", false, result);
    }
}
